package es.usc.citius.servando.calendula.util.security;

import android.content.Context;
import android.content.SharedPreferences;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableEntryException;
import java.security.cert.CertificateException;

import javax.crypto.NoSuchPaddingException;

import devliving.online.securedpreferencestore.DefaultRecoveryHandler;
import devliving.online.securedpreferencestore.SecuredPreferenceStore;
import es.usc.citius.servando.calendula.util.LogUtil;
import es.usc.citius.servando.calendula.util.PreferenceUtils;

public class SecurityProvider {
    private static final String TAG = "SecurityProvider";

    private static final String STORE_NAME = "secure_vault";
    private static final String STORE_PREFIX = "vault_pref";
    private static final String SEED_KEY = "CalendulaVault";

    private static SecuredPreferenceStore securedPrefStore;
    private static WeakReference encryptionProvider;

    public static void init(Context ctx) {
        try {
            SecuredPreferenceStore.init(
                    ctx.getApplicationContext(),
                    STORE_NAME,
                    STORE_PREFIX,
                    SEED_KEY.getBytes(),
                    new DefaultRecoveryHandler()
            );
        } catch (IOException | CertificateException
                | NoSuchAlgorithmException | KeyStoreException
                | UnrecoverableEntryException | InvalidAlgorithmParameterException
                | NoSuchPaddingException | InvalidKeyException
                | NoSuchProviderException | SecuredPreferenceStore.MigrationFailedException e) {
            e.printStackTrace();
        }
        securedPrefStore = SecuredPreferenceStore.getSharedInstance();
        encryptionProvider = null;
    }

    private static boolean isAvailable() {
        return securedPrefStore != null;
    }

    public static EncryptionProvider getEncryptionProvider() {

        if (encryptionProvider == null) {
            if (isAvailable()) {
                encryptionProvider = new WeakReference(new LibraryEncryptionProvider(securedPrefStore.getEncryptionManager()));
            } else {
                LogUtil.w(
                        TAG,
                        "getEncryptionProvider: SecurityProvider not initialized! Not using encryption. Is this what you want?"
                );
                encryptionProvider = new WeakReference(new NoopEncryptionProvider());
            }
        }

        return (EncryptionProvider) encryptionProvider.get();
    }

    private SharedPreferences getPreferences() {
        if (isAvailable()) {
            return (SharedPreferences)securedPrefStore;
        } else {
            LogUtil.w(
                    TAG,
                    "getPreferences: SecurityProvider not initialized! Not using encryption. Is this what you want?"
            );
            return PreferenceUtils.instance().preferences();
        }
    }
}
